package com.henry.chatkit.input

import android.annotation.SuppressLint
import android.content.Context
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View.OnClickListener
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.FragmentManager
import com.henry.chatkit.R
import com.henry.chatkit.utils.AudioPlayer
import com.henry.chatkit.utils.ChatTool
import com.henry.chatkit.utils.log
import java.util.*


open class InputLayout : InputLayoutUI {

    enum class InputState {
        none, voice, face, more, input
    }

    private var mCurrentState = InputState.none

    private var mInputContent: String? = null
    private var mSendEnable = false
    private var mLastMsgLineCount = 0

    private var mMessageHandler: MessageHandler? = null

    private var mInputMoreFragment: InputMoreFragment? = null
    private var mFragmentManager: FragmentManager? = null

    var mInputMoreActionList = mutableListOf<InputMoreActionUnit>()
    var mInputMoreCustomActionList = mutableListOf<InputMoreActionUnit>()

    private var mAudioCancel = false
    private var mStartRecordY = 0f
    private var mChatInputHandler: ChatInputHandler? = null

    fun setMessageHandler(handler: MessageHandler) {
        mMessageHandler = handler
    }

    fun setChatInputHandler(handler: ChatInputHandler?) {
        mChatInputHandler = handler
    }

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    @SuppressLint("ClickableViewAccessibility")
    override fun initView() {

        input.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                mInputContent = s.toString()
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

            }

            override fun afterTextChanged(s: Editable?) {
                if (TextUtils.isEmpty(s.toString().trim { it <= ' ' })) {
                    mSendEnable = false
                    showSendButton(GONE)
                    showMoreButton(VISIBLE)
                } else {
                    mSendEnable = true
                    showSendButton(VISIBLE)
                    showMoreButton(GONE)
                    if (input.lineCount != mLastMsgLineCount) {
                        mLastMsgLineCount = input.lineCount!!
//                        if (mChatInputHandler != null) {
//                            mChatInputHandler.onInputAreaClick()
//                        }
                    }

                    // TODO 百度输入法长按不能连续删除，是由于表情处理耗时吗，其他输入就没问题😇😇😇
//                    if (!TextUtils.equals(mInputContent, binding.input.text.toString())) {
//                        FaceManager.handlerEmojiText(binding.input, binding.input.text.toString());
//                    }
                }
            }

        })

        input.setOnTouchListener { v, event ->
            mCurrentState = InputState.input
            showSoftInput()
            return@setOnTouchListener false
        }

        audioButton.setOnClickListener {
            when (mCurrentState) {
                InputState.voice -> {
                    mCurrentState = InputState.input
                }
                InputState.input -> {
                    mCurrentState = InputState.voice
                    hideSoftInput()
                }
                InputState.more -> {
                    mCurrentState = InputState.voice
                    hideInputMoreLayout()
                    moreButton.setImageResource(R.drawable.chat_input_more)
                }
                InputState.face -> {
                    mCurrentState = InputState.voice
                    faceButton.setImageResource(R.drawable.chat_input_face)
                }
                else -> {
                    mCurrentState = InputState.voice
                }
            }

            if (mCurrentState == InputState.voice) {
                audioButton.setImageResource(R.drawable.chat_input_input)
                input.visibility = GONE
                voiceButton.visibility = VISIBLE
            } else {
                audioButton.setImageResource(R.drawable.chat_input_audio)
                input.visibility = VISIBLE
                voiceButton.visibility = GONE
            }
            if (mCurrentState == InputState.input) {
                showSoftInput()
            }
        }
        faceButton.setOnClickListener {

        }
        moreButton.setOnClickListener {
            when (mCurrentState) {
                InputState.voice -> {
                    mCurrentState = InputState.more
                    audioButton.setImageResource(R.drawable.chat_input_audio)
                    input.visibility = VISIBLE
                    voiceButton.visibility = GONE
                }
                InputState.input -> {
                    mCurrentState = InputState.more
                    hideSoftInput()
                }
                InputState.face -> {
                    mCurrentState = InputState.more
                }
                InputState.more -> {
                    mCurrentState = InputState.input
                    showSoftInput()
                }
                else -> {
                    mCurrentState = InputState.more
                }
            }

            if (mCurrentState == InputState.more) {
                showInputMoreLayout()
                moreButton.setImageResource(R.drawable.chat_input_input)
            } else {
                hideInputMoreLayout()
                moreButton.setImageResource(R.drawable.chat_input_more)
            }

            if (mChatInputHandler != null) {
                postDelayed({ mChatInputHandler!!.onInputAreaClick() }, 200)
            }
        }

        // 长按录音
        voiceButton.setOnTouchListener { v, event ->
            checkPermission(AUDIO_RECORD) {
                if (it) {
                    handleEvent(event)
                }
            }
            return@setOnTouchListener true
        }
        sendButton.setOnClickListener {
            if (mSendEnable) {
                mMessageHandler?.sendMessage(input.text.toString().trim())
                input.setText("")
            }
        }

    }

    private fun handleEvent(event: MotionEvent) {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                mAudioCancel = true
                mStartRecordY = event.y
                mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_START)
                voiceButton.text = "松开结束"
                AudioPlayer.instance.startRecord(object : AudioPlayer.Callback {
                    override fun onCompletion(success: Boolean) {
                        recordComplete(success)
                    }
                })
            }
            MotionEvent.ACTION_MOVE -> {
                if (event.y - mStartRecordY < -100) {
                    mAudioCancel = true
                    mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_CANCEL)
                } else {
                    if (mAudioCancel) {
                        mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_START)
                    }
                    mAudioCancel = false
                }
                voiceButton.text = "松开结束"
            }
            MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
                mAudioCancel = event.y - mStartRecordY < -100
                mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_STOP)
                voiceButton.text = "按住说话"
                AudioPlayer.instance.stopRecord()
            }

        }
    }

    private fun recordComplete(success: Boolean) {
        val duration: Int = AudioPlayer.instance.getDuration()
        if (!success || duration == 0) {
            mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_FAILED)
            return
        }
        if (mAudioCancel) {
            mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_CANCEL)
            return
        }
        if (duration < 1000) {
            mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_TOO_SHORT)
            return
        }
        mChatInputHandler?.onRecordStatusChanged(ChatInputHandler.RECORD_STOP)

        // 取秒
        mMessageHandler?.sendAudioMessage(AudioPlayer.instance.getPath() ?: "", duration / 1000)

    }

    private fun showInputMoreLayout() {
        if (mFragmentManager == null) {
            mFragmentManager = mActivity!!.supportFragmentManager
        }
        if (mInputMoreFragment == null) {
            mInputMoreFragment = InputMoreFragment()
        }

        assembleActions()

        mInputMoreFragment!!.setActions(mInputMoreActionList)

        hideSoftInput()

        moreGroups.visibility = VISIBLE
        mFragmentManager!!.beginTransaction().replace(R.id.moreGroups, mInputMoreFragment!!).commitAllowingStateLoss()

    }

    private fun hideInputMoreLayout() {
        moreGroups.visibility = GONE
    }

    fun assembleActions() {
        mInputMoreActionList.clear()
        val action = InputMoreActionUnit()
        action.iconResId = R.drawable.chat_more_icons_photo
        action.title = "图片"
        action.onClickListener = OnClickListener {
            hideInput()

            mInputMoreFragment?.let { it1 ->
                ChatTool.openPhoto(it1, 1) {

                    for (media in it) {
                        if (media == null) {
                            break
                        }
                        val path = media.compressPath
                        val width = media.width
                        val height = media.height

                        log( "是否压缩:" + media.isCompressed)
                        log( "压缩:" + media.compressPath)
                        log(" 原图:" + media.path)
                        log( "绝对路径:" + media.realPath)
                        log( "是否裁剪:" + media.isCut)
                        log( "裁剪:" + media.cutPath)
                        log( "是否开启原图:" + media.isOriginal)
                        log( "原图路径:" + media.originalPath)
                        log( "Android Q 特有Path:" + media.androidQToPath)
                        log( "宽高: " + media.width + "x" + media.height)
                        log( "Size: " + media.size)

                        mMessageHandler?.sendImageMessage(path, width, height)
                    }

                    // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息，如旋转角度、经纬度等信息

                }
            }

        }
        mInputMoreActionList.add(action)

        val action1 = InputMoreActionUnit()
        action1.iconResId = R.drawable.chat_more_icons_camera
        action1.title = "拍照"
        action1.onClickListener = OnClickListener {
            hideInput()

            mInputMoreFragment?.let { it1 ->
                ChatTool.openCamera(it1) {
                    for (media in it) {
                        if (media == null) {
                            break
                        }
                        val path = media.compressPath
                        val width = media.width
                        val height = media.height

                        log( "是否压缩:" + media.isCompressed)
                        log( "压缩:" + media.compressPath)
                        log(" 原图:" + media.path)
                        log( "绝对路径:" + media.realPath)
                        log( "是否裁剪:" + media.isCut)
                        log( "裁剪:" + media.cutPath)
                        log( "是否开启原图:" + media.isOriginal)
                        log( "原图路径:" + media.originalPath)
                        log( "Android Q 特有Path:" + media.androidQToPath)
                        log( "宽高: " + media.width + "x" + media.height)
                        log( "Size: " + media.size)

                        mMessageHandler?.sendImageMessage(path, width, height)
                    }
                }
            }

        }
        mInputMoreActionList.add(action1)

        mInputMoreActionList.addAll(mInputMoreCustomActionList)

    }

    open fun addAction(action: InputMoreActionUnit) {
        mInputMoreCustomActionList.add(action)
    }

    open fun clearCustomAction() {
        mInputMoreCustomActionList.clear()
    }

    private fun showSoftInput() {
        hideInputMoreLayout()
        audioButton.setImageResource(R.drawable.chat_input_audio)
        faceButton.setImageResource(R.drawable.chat_input_face)
        moreButton.setImageResource(R.drawable.chat_input_more)

        input.requestFocus()
        val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(input, 0)

        if (mChatInputHandler != null) {
            postDelayed({ mChatInputHandler!!.onInputAreaClick() }, 200)
        }
    }

    private fun hideSoftInput() {
        faceButton.setImageResource(R.drawable.chat_input_face)
        moreButton.setImageResource(R.drawable.chat_input_more)

        val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(input.windowToken, 0)
        input.clearFocus()
        hideInputMoreLayout()
    }

    fun hideInput() {
        mCurrentState = InputState.none

        faceButton.setImageResource(R.drawable.chat_input_face)
        moreButton.setImageResource(R.drawable.chat_input_more)

        val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(input.windowToken, 0)
        input.clearFocus()
        hideInputMoreLayout()
    }

    fun hideKeyword() {
        val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(input.windowToken, 0)
        input.clearFocus()
    }

    interface MessageHandler {
        fun sendMessage(msg: String?)
        fun sendAudioMessage(path: String, duration: Int)
        fun sendImageMessage(path: String, width: Int, height: Int)
    }

    interface ChatInputHandler {
        fun onInputAreaClick()
        fun onRecordStatusChanged(status: Int)

        companion object {
            const val RECORD_START = 1
            const val RECORD_STOP = 2
            const val RECORD_CANCEL = 3
            const val RECORD_TOO_SHORT = 4
            const val RECORD_FAILED = 5
        }
    }

}